xen: Cleanups and bug fixes after the rcu_lock_domain patch.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 1 Mar 2007 11:38:55 +0000 (11:38 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 1 Mar 2007 11:38:55 +0000 (11:38 +0000)
Signed-off-by: Keir Fraser <keir@xensource.com>
12 files changed:
xen/arch/ia64/vmx/vmx_hypercall.c
xen/arch/ia64/xen/mm.c
xen/arch/powerpc/mm.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/mm.c
xen/common/domain.c
xen/common/domctl.c
xen/common/event_channel.c
xen/common/grant_table.c
xen/common/schedule.c
xen/common/sysctl.c
xen/include/xen/sched.h

index 24bde7d094275cca2484476566e23f41e681f618..46a9bdb87f8e291513ae5f73c3fead8b448d5d59 100644 (file)
@@ -122,8 +122,7 @@ do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
             return -EINVAL;
 
         if (a.domid == DOMID_SELF) {
-            get_knownalive_domain(current->domain);
-            d = current->domain;
+            d = get_current_domain();
         }
         else if (IS_PRIV(current->domain)) {
             d = get_domain_by_id(a.domid);
index b1efa6293facc3118dbb6e3fb4f23374c6c1e279..543ffa1e4da3eb0aedff654046b10a333c7f9551 100644 (file)
@@ -435,11 +435,15 @@ share_xen_page_with_guest(struct page_info *page,
     page_set_owner(page, d);
     wmb(); /* install valid domain ptr before updating refcnt. */
     ASSERT(page->count_info == 0);
-    page->count_info |= PGC_allocated | 1;
 
-    if ( unlikely(d->xenheap_pages++ == 0) )
-        get_knownalive_domain(d);
-    list_add_tail(&page->list, &d->xenpage_list);
+    /* Only add to the allocation list if the domain isn't dying. */
+    if ( !test_bit(_DOMF_dying, &d->domain_flags) )
+    {
+        page->count_info |= PGC_allocated | 1;
+        if ( unlikely(d->xenheap_pages++ == 0) )
+            get_knownalive_domain(d);
+        list_add_tail(&page->list, &d->xenpage_list);
+    }
 
     // grant_table_destroy() releases these pages.
     // but it doesn't clear their m2p entry. So there might remain stale
@@ -2057,8 +2061,7 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
             return -EFAULT;
 
         if (xatp.domid == DOMID_SELF) {
-            d = current->domain;
-            get_knownalive_domain(d);
+            d = get_current_domain();
         }
         else if (!IS_PRIV(current->domain))
             return -EPERM;
index ab83d09b558ea3075ebd6279f020157e35ece759..5f257dcc8581e14ae6aff4c01e22c7abbbe45266 100644 (file)
@@ -80,11 +80,15 @@ void share_xen_page_with_guest(
     page_set_owner(page, d);
     wmb(); /* install valid domain ptr before updating refcnt. */
     ASSERT(page->count_info == 0);
-    page->count_info |= PGC_allocated | 1;
 
-    if ( unlikely(d->xenheap_pages++ == 0) )
-        get_knownalive_domain(d);
-    list_add_tail(&page->list, &d->xenpage_list);
+    /* Only add to the allocation list if the domain isn't dying. */
+    if ( !test_bit(_DOMF_dying, &d->domain_flags) )
+    {
+        page->count_info |= PGC_allocated | 1;
+        if ( unlikely(d->xenheap_pages++ == 0) )
+            get_knownalive_domain(d);
+        list_add_tail(&page->list, &d->xenpage_list);
+    }
 
     spin_unlock(&d->page_alloc_lock);
 }
index 073ad836d2ed3283cb99d866ac7b19bffc5ade60..bda506b182974156d49feb0cbdf9b5e08e170fd4 100644 (file)
@@ -836,20 +836,14 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
             return -EINVAL;
 
         if ( a.domid == DOMID_SELF )
-        {
-            get_knownalive_domain(current->domain);
-            d = current->domain;
-        }
+            d = rcu_lock_current_domain();
         else if ( IS_PRIV(current->domain) )
-        {
             d = rcu_lock_domain_by_id(a.domid);
-            if ( d == NULL )
-                return -ESRCH;
-        }
         else
-        {
             return -EPERM;
-        }
+
+        if ( d == NULL )
+            return -ESRCH;
 
         rc = -EINVAL;
         if ( !is_hvm_domain(d) )
index 358ae84081f3c42f038601cd485b65c7b4cdb568..10f5a86b4dd4fa2b9e51e70caec668c988fc1b0d 100644 (file)
@@ -263,11 +263,15 @@ void share_xen_page_with_guest(
     page_set_owner(page, d);
     wmb(); /* install valid domain ptr before updating refcnt. */
     ASSERT(page->count_info == 0);
-    page->count_info |= PGC_allocated | 1;
 
-    if ( unlikely(d->xenheap_pages++ == 0) )
-        get_knownalive_domain(d);
-    list_add_tail(&page->list, &d->xenpage_list);
+    /* Only add to the allocation list if the domain isn't dying. */
+    if ( !test_bit(_DOMF_dying, &d->domain_flags) )
+    {
+        page->count_info |= PGC_allocated | 1;
+        if ( unlikely(d->xenheap_pages++ == 0) )
+            get_knownalive_domain(d);
+        list_add_tail(&page->list, &d->xenpage_list);
+    }
 
     spin_unlock(&d->page_alloc_lock);
 }
@@ -2960,10 +2964,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
             return -EFAULT;
 
         if ( xatp.domid == DOMID_SELF )
-        {
-            d = current->domain;
-            get_knownalive_domain(d);
-        }
+            d = rcu_lock_current_domain();
         else if ( !IS_PRIV(current->domain) )
             return -EPERM;
         else if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL )
@@ -3039,10 +3040,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
             return -EINVAL;
 
         if ( fmap.domid == DOMID_SELF )
-        {
-            d = current->domain;
-            get_knownalive_domain(d);
-        }
+            d = rcu_lock_current_domain();
         else if ( !IS_PRIV(current->domain) )
             return -EPERM;
         else if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL )
index 551b9f8e235aebd354323208f85bc321a7f3f8de..c1a1dc2b4eddba85a34d8748ca5e5f216a812325 100644 (file)
@@ -345,8 +345,7 @@ void domain_pause_for_debugger(void)
     send_guest_global_virq(dom0, VIRQ_DEBUGGER);
 }
 
-/* Complete domain destroy after RCU readers are not holding 
-   old references */
+/* Complete domain destroy after RCU readers are not holding old references. */
 static void complete_domain_destroy(struct rcu_head *head)
 {
     struct domain *d = container_of(head, struct domain, rcu);
@@ -390,7 +389,7 @@ void domain_destroy(struct domain *d)
     rcu_assign_pointer(*pd, d->next_in_hashbucket);
     spin_unlock(&domlist_update_lock);
 
-    /* schedule RCU asynchronous completion of domain destroy */
+    /* Schedule RCU asynchronous completion of domain destroy. */
     call_rcu(&d->rcu, complete_domain_destroy);
 }
 
index 50479532bc9b2732da668f4e0854d36784f8fc1b..fd85b8cbd8382c4e0a5926184a911fd6dfdd4b32 100644 (file)
@@ -484,22 +484,20 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
                 break;
         }
 
-        if ( (d == NULL) || !get_domain(d) )
+        if ( d == NULL )
         {
             rcu_read_unlock(&domlist_read_lock);
             ret = -ESRCH;
             break;
         }
 
-        rcu_read_unlock(&domlist_read_lock);
-
         getdomaininfo(d, &op->u.getdomaininfo);
 
         op->domain = op->u.getdomaininfo.domain;
         if ( copy_to_guest(u_domctl, op, 1) )
             ret = -EFAULT;
 
-        put_domain(d);
+        rcu_read_unlock(&domlist_read_lock);
     }
     break;
 
index 9a786ad4a09e7fbf3feed86374f7ee9af72a993a..2b361f501e9bd6e701e6cb090376e64e2e85fb34 100644 (file)
@@ -434,7 +434,7 @@ static long __evtchn_close(struct domain *d1, int port1)
             spin_unlock(&d2->evtchn_lock);
         put_domain(d2);
     }
-    
+
     spin_unlock(&d1->evtchn_lock);
 
     return rc;
index b0818311b08abb292b5b470372d497a78ac54ce6..68d1fa2d8cada90dca2d3a7a50eced8ad998372d 100644 (file)
@@ -1086,26 +1086,16 @@ __gnttab_copy(
                  "only allow copy-by-mfn for DOMID_SELF.\n");
 
     if ( op->source.domid == DOMID_SELF )
-    {
-        sd = current->domain;
-        get_knownalive_domain(sd);
-    }
+        sd = rcu_lock_current_domain();
     else if ( (sd = rcu_lock_domain_by_id(op->source.domid)) == NULL )
-    {
         PIN_FAIL(error_out, GNTST_bad_domain,
                  "couldn't find %d\n", op->source.domid);
-    }
 
     if ( op->dest.domid == DOMID_SELF )
-    {
-        dd = current->domain;
-        get_knownalive_domain(dd);
-    }
+        dd = rcu_lock_current_domain();
     else if ( (dd = rcu_lock_domain_by_id(op->dest.domid)) == NULL )
-    {
         PIN_FAIL(error_out, GNTST_bad_domain,
                  "couldn't find %d\n", op->dest.domid);
-    }
 
     if ( src_is_gref )
     {
index 8f1f755d277e985f52b6ffd494c8603543e935a6..8ba192d0acb623c07200dce70f3ceaeaa96dc749 100644 (file)
@@ -430,12 +430,12 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg)
             break;
 
         ret = -ESRCH;
-        d = get_domain_by_id(sched_remote_shutdown.domain_id);
+        d = rcu_lock_domain_by_id(sched_remote_shutdown.domain_id);
         if ( d == NULL )
             break;
 
         domain_shutdown(d, (u8)sched_remote_shutdown.reason);
-        put_domain(d);
+        rcu_unlock_domain(d);
         ret = 0;
 
         break;
index 399523ecfd4d77c025779dff0499467c1e34a675..789e643ff249f3360c628ba81d6f62b241930922 100644 (file)
@@ -86,16 +86,9 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
                 continue;
             if ( num_domains == op->u.getdomaininfolist.max_domains )
                 break;
-            if ( (d == NULL) || !get_domain(d) )
-            {
-                ret = -ESRCH;
-                break;
-            }
 
             getdomaininfo(d, &info);
 
-            put_domain(d);
-
             if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer,
                                       num_domains, &info, 1) )
             {
index 6fb03a807fa71b22b794a560a83bb0764afa8c4d..cbfb67a9e796ea5df3590baaf91689e8711d4686 100644 (file)
@@ -258,6 +258,14 @@ static inline void get_knownalive_domain(struct domain *d)
     ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
 }
 
+/* Obtain a reference to the currently-running domain. */
+static inline struct domain *get_current_domain(void)
+{
+    struct domain *d = current->domain;
+    get_knownalive_domain(d);
+    return d;
+}
+
 struct domain *domain_create(domid_t domid, unsigned int domcr_flags);
  /* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */
 #define _DOMCRF_hvm 0
@@ -284,6 +292,12 @@ static inline void rcu_unlock_domain(struct domain *d)
     rcu_read_unlock(&domlist_read_lock);
 }
 
+static inline struct domain *rcu_lock_current_domain(void)
+{
+    rcu_read_lock(&domlist_read_lock);
+    return current->domain;
+}
+
 struct domain *get_domain_by_id(domid_t dom);
 void domain_destroy(struct domain *d);
 void domain_kill(struct domain *d);